package cn.bonoon.handler.impl;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.util.StringUtils;

import cn.bonoon.core.plugins.LoginRecordService;
import cn.bonoon.handler.LoginSuccessHandler;
import cn.bonoon.kernel.menus.IModuleInfo;
import cn.bonoon.kernel.menus.ModuleManager;
import cn.bonoon.kernel.security.LogonUser;
import cn.bonoon.kernel.support.services.UserService;
import cn.bonoon.kernel.util.RequestHelper;

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {

	private final Log logger = LogFactory.getLog(this.getClass());
    
	@Autowired
	@Qualifier("httpSessionRequestCache")
	private RequestCache requestCache;
	
	@Autowired
	private LoginRecordService loginRecordSevice;
	
	@Autowired(required = false)
	private List<LoginSuccessHandler> handlers;
	@Autowired
	private UserService userService;
	@Autowired
	private ModuleManager moduleManager;
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    private String targetUrlParameter = null;
    
	public AuthenticationSuccessHandlerImpl() {
		targetUrlParameter = "redirect-url";
	}

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
		LogonUser bu = (LogonUser) authentication.getPrincipal();
		try {
			loginRecordSevice.login(bu, RequestHelper.getAgent(request), RequestHelper.getIpAddress(request), true, request.getSession().getId());
		} catch (Throwable err) {
			// 忽略所有异常情况
			err.printStackTrace();
			logger.error("写登录记录异常", err);
		}
		
		try {
			if (null != handlers && !handlers.isEmpty()) {
				for (LoginSuccessHandler handler : handlers) {
					handler.onSuccess(request, response, authentication, bu);
				}
			}
		} catch (Throwable err) {
			err.printStackTrace();
			logger.error("子系统或插件定义的处理异常", err);
		}

		SavedRequest savedRequest = requestCache.getRequest(request, response);
		if (savedRequest == null) {

	        String targetUrl = null;// = determineTargetUrl(request, response);

	        if (targetUrlParameter != null  ) {
	            targetUrl = request.getParameter(targetUrlParameter);
	        }

            if (!StringUtils.hasText(targetUrl)) {
            	if(bu.allowAccess()){
            		//targetUrl = moduleManager.getEndpoint();

    				for(String key : userService.accessableModules(bu)){
    					IModuleInfo module = moduleManager.module(key);
    					if(null != module){
    						//i = _parse(i, hostmain, module, errPicSrc);
    						targetUrl = module.getEndpoint();
    						break;
    					}
    				}
    				if (!StringUtils.hasText(targetUrl)) {
    					targetUrl = moduleManager.getEndpoint();
    				}
				}else{
					targetUrl = moduleManager.getDefaultEndpoint();
				}
            }
	        
	        if (response.isCommitted()) {
	            logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
	            return;
	        }

	        redirectStrategy.sendRedirect(request, response, targetUrl);
	        clearAuthenticationAttributes(request);
		}else{
			requestCache.removeRequest(request, response);
			clearAuthenticationAttributes(request);
	
			// Use the DefaultSavedRequest URL
			String targetUrl = savedRequest.getRedirectUrl();
			logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
			redirectStrategy.sendRedirect(request, response, targetUrl);
		}
	}

    /**
     * Removes temporary authentication-related data which may have been stored in the session
     * during the authentication process.
     */
    protected final void clearAuthenticationAttributes(HttpServletRequest request) {
        HttpSession session = request.getSession(false);

        if (session == null) {
            return;
        }

        session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
    }

    /**
     * Allows overriding of the behaviour when redirecting to a target URL.
     */
    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }

    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
}
